﻿#include "MainWindow.h"
#include <iostream>
#include <QMenuBar>
#include <QToolBar>
#include <QStatusBar>
#include <QDockWidget>
#include <QMessageBox>
#include <QFileDialog>
#include <qgsproject.h>
#include <QgsMapLayer.h>
#include <QVector>
#include <QtMath>
#include <random>
#include <QVariant>
#include <QgsVectorLayerExporter.h>
#include <QgsRasterPipe.h>
#include <QgsRasterFileWriter.h>
#include <QgsProjectionSelectionWidget.h>
#include <gdal.h>
#include "gdal_priv.h"
#include "cpl_conv.h"
#include "ogr_spatialref.h"
#include "ogrsf_frmts.h"
#include <qgsstylemanagerdialog.h>  // 样式管理器的头文件

MainWindow::MainWindow(QWidget* parent)
	: QMainWindow(parent),
	mpMapCanvas(new QgsMapCanvas(this)),
	mpFileTreeWidget(new QTreeWidget(this)),
	mpLayerTreeView(new QgsLayerTreeView(this)),
	mLayerManager(new LayerManager(mpMapCanvas, mpFileTreeWidget, mpLayerTreeView, this)),
	mVectorAnalysis(new VectorAnalysis(mpMapCanvas, this)),
	mRasterAnalysis(new RasterAnalysis(mpMapCanvas, this)),
	mEditView(new EditView(mpMapCanvas, this)),
	mDataFrameCrsSet(false)
{
	setMinimumSize(QSize(1800, 1100));
	setWindowTitle("ArkGIS");

	// 创建窗口各组件
	createMenuBar();
	createToolBar();
	createDockWidgets();
	createMapCanvas();
	createStatusBar();

	// 导入样式表
	QFile file("./theme.qss");
	if (file.open(QFile::ReadOnly | QFile::Text)) {
		QTextStream stream(&file);
		qApp->setStyleSheet(stream.readAll());
		file.close();
	}

	updateVectorLayersComboBox();
}

MainWindow::~MainWindow()
{

}

// 创建菜单栏
void MainWindow::createMenuBar()
{
	QMenuBar* mpMenuBar = new QMenuBar(this);
	QMenu* mpProjectMenu = mpMenuBar->addMenu(tr("工程(&J)"));
	mpProjectMenu->addAction(tr("打开工程文件"), this, &MainWindow::openProject);
	mpProjectMenu->addAction(tr("保存工程文件"), this, &MainWindow::saveProject);

	QMenu* mpEditMenu = mpMenuBar->addMenu(tr("编辑(&E)"));
	QMenu* mpViewMenu = mpMenuBar->addMenu(tr("视图(&V)"));

	QMenu* mpLayerMenu = mpMenuBar->addMenu(tr("图层(&L)"));
	mpLayerMenu->addAction(tr("按类别符号化图层-唯一值"), mLayerManager, &LayerManager::performCategorizedSymbology);

	QMenu* mpAddlayerMenu = mpLayerMenu->addMenu(tr("添加图层"));
	mpAddlayerMenu->addAction(tr("矢量图层"), mLayerManager, &LayerManager::addVectorLayer);
	mpAddlayerMenu->addAction(tr("栅格图层"), mLayerManager, &LayerManager::addRasterLayer);
	mpAddlayerMenu->addAction(tr("分隔符文本图层"), mLayerManager, &LayerManager::addDelimitedTextLayer);

	QMenu* mpSettingsMenu = mpMenuBar->addMenu(tr("设置(&S)"));
	mpSettingsMenu->addAction(tr("数据框坐标系"), this, &MainWindow::openDataFrameCrsDialog);
	mpSettingsMenu->addAction(tr("QGIS样式管理器"), this, &MainWindow::openStyleManager);
	mpSettingsMenu->addAction(tr("ArkGIS样式管理器"), this, &MainWindow::openSymbolManager);

	QMenu* mpVectorMenu = mpMenuBar->addMenu(tr("矢量(&O)"));
	mpVectorMenu->addAction(tr("K均值聚类"), mVectorAnalysis, &VectorAnalysis::performKMeansClustering);
	mpVectorMenu->addAction(tr("按位置连接属性"), mVectorAnalysis, &VectorAnalysis::performSpatialJoin);

	QMenu* mpRasterMenu = mpMenuBar->addMenu(tr("栅格(&R)"));
	mpRasterMenu->addAction(tr("栅格图层统计"), mRasterAnalysis, &RasterAnalysis::performRasterLayerStatistics);

	QMenu* mpDatabaseMenu = mpMenuBar->addMenu(tr("数据库(&D)"));
	QMenu* mpWebMenu = mpMenuBar->addMenu(tr("Web(&W)"));
	QMenu* mpMeshMenu = mpMenuBar->addMenu(tr("网孔(&M)"));

	QMenu* mpProcessMenu = mpMenuBar->addMenu(tr("数据处理(&C)"));
	mpProcessMenu->addAction(tr("投影变换"), this, &MainWindow::performProjectionTransformation);

	QMenu* mpHelpMenu = mpMenuBar->addMenu(tr("帮助(&H)"));
	setMenuBar(mpMenuBar);
}

// 创建工具栏
void MainWindow::createToolBar()
{
	// 主工具栏
	QToolBar* mpMainToolBar = addToolBar(tr("Main Toolbar"));
	mpMainToolBar->setIconSize(QSize(50, 50));
	mpMainToolBar->addAction(QIcon("./icons/1.png"), tr("打开工程"), this, &MainWindow::openProject);
	mpMainToolBar->addAction(QIcon("./icons/2.png"), tr("保存工程"), this, &MainWindow::saveProject);
	mpMainToolBar->addAction(QIcon("./icons/3.png"), tr("退出"), this, &MainWindow::close);

	QToolBar* mpEditToolBar = addToolBar(tr("Edit Toolbar"));
	mpEditLayerComboBox = new QComboBox(this);
	mpEditLayerComboBox->setObjectName("选择编辑图层");
	mpEditLayerComboBox->setEditable(false);
	connect(mLayerManager, &LayerManager::layersChanged, this, &MainWindow::updateVectorLayersComboBox);

	// 初始化编辑模式按钮
	mpEditAction = new QAction(QIcon("./icons/edit.png"), tr("编辑模式"), this);
	mpEditAction->setCheckable(true);
	mpEditAction->setChecked(false);
	connect(mpEditAction, &QAction::triggered, this, &MainWindow::onEditButtonClicked);

	// 初始化创建点按钮
	mpCreatePointAction = new QAction(QIcon("./icons/9.png"), tr("创建点"), this);
	mpCreatePointAction->setEnabled(false);
	connect(mpCreatePointAction, &QAction::triggered, this, &MainWindow::onCreatePointClicked);

	// 初始化创建线按钮
	mpCreateLineAction = new QAction(QIcon("./icons/10.png"), tr("创建线"), this);
	mpCreateLineAction->setEnabled(false);
	connect(mpCreateLineAction, &QAction::triggered, this, &MainWindow::onCreateLineClicked);

	// 初始化创建面按钮
	mpCreatePolygonAction = new QAction(QIcon("./icons/11.png"), tr("创建面"), this);
	mpCreatePolygonAction->setEnabled(false);
	connect(mpCreatePolygonAction, &QAction::triggered, this, &MainWindow::onCreatePolygonClicked);

	// 初始化保存编辑按钮
	mpSaveEditAction = new QAction(QIcon("./icons/saveeditlayer.png"), tr("保存编辑"), this);
	mpSaveEditAction->setEnabled(false);
	connect(mpSaveEditAction, &QAction::triggered, this, &MainWindow::onEditSaveClicked);

	// 初始化取消编辑按钮
	mpCancelEditAction = new QAction(QIcon("./icons/canceledit.png"), tr("取消编辑"), this);
	mpCancelEditAction->setEnabled(false);
	connect(mpCancelEditAction, &QAction::triggered, this, &MainWindow::onEditCancelClicked);

	// 将编辑相关的控件添加到工具栏
	mpEditToolBar->addWidget(mpEditLayerComboBox);
	mpEditToolBar->addAction(mpEditAction);
	mpEditToolBar->addAction(mpCreatePointAction);
	mpEditToolBar->addAction(mpCreateLineAction);
	mpEditToolBar->addAction(mpCreatePolygonAction);
	mpEditToolBar->addAction(mpSaveEditAction);
	mpEditToolBar->addAction(mpCancelEditAction);

	// 编辑工具栏
	QToolBar* mpToolBar = addToolBar(tr("MoveToolbar"));
	mpToolBar->setIconSize(QSize(50, 50));
	mpToolBar->addAction(QIcon("./icons/4.png"), tr("选择"));
	mpToolBar->addAction(QIcon("./icons/5.png"), tr("移动"));
	mpToolBar->addAction(QIcon("./icons/6.png"), tr("放大"));
	mpToolBar->addAction(QIcon("./icons/7.png"), tr("缩小"));
	mpToolBar->addAction(QIcon("./icons/8.png"), tr("复位"), this, &MainWindow::zoomToLayer);
	mpToolBar->addAction(QIcon("./icons/12.png"), tr("保存"));
	mpToolBar->addAction(QIcon("./icons/13.png"), tr("取消"));
	mpToolBar->addAction(QIcon("./icons/proj.png"), tr("投影变换"), this, &MainWindow::performProjectionTransformation);
	mpToolBar->addAction(QIcon("./icons/14.png"), tr("关于"), this, &MainWindow::about);


}

void MainWindow::zoomToLayer()
{
	// 获取当前选中的图层
	QgsMapLayer* layer = mpLayerTreeView->currentLayer();
	if (!layer)
		return;

	// 获取图层范围并更新地图画布
	mpMapCanvas->setExtent(layer->extent());
	mpMapCanvas->refresh();
}

void MainWindow::setEditState(bool enabled)
{
	// 更新编辑状态
	mpCreatePointAction->setEnabled(enabled);
	mpCreateLineAction->setEnabled(enabled);
	mpCreatePolygonAction->setEnabled(enabled);
	mpSaveEditAction->setEnabled(enabled);
	mpCancelEditAction->setEnabled(enabled);
	emit editStateChanged(enabled);
}

void MainWindow::updateVectorLayersComboBox()
{
	// 保存当前选中的图层名称
	QString currentLayerName = mpEditLayerComboBox->currentText();

	// 清空现有的下拉框选项
	mpEditLayerComboBox->clear();

	// 获取QGIS项目实例
	QgsProject* project = QgsProject::instance();

	// 遍历项目中的所有图层
	const auto layers = project->mapLayers().values();
	for (const QgsMapLayer* layer : layers) {
		// 检查图层是否为矢量图层
		if (layer->type() == Qgis::LayerType::Vector) {
			// 将矢量图层名称添加到下拉框中
			mpEditLayerComboBox->addItem(layer->name());
		}
	}

	// 恢复之前的选择
	int index = mpEditLayerComboBox->findText(currentLayerName);
	if (index != -1) {
		mpEditLayerComboBox->setCurrentIndex(index);
	}
	else if (mpEditLayerComboBox->count() > 0) {
		// 如果当前选中的图层不再存在，设置第一个图层为选中状态
		mpEditLayerComboBox->setCurrentIndex(0);
	}
}

void MainWindow::onEditButtonClicked()
{
	bool editEnabled = mpEditAction->isChecked();
	setEditState(editEnabled);
	if (editEnabled) {
		// 获取当前选中的图层名称
		QString currentLayerName = mpEditLayerComboBox->currentText();
		// 获取QGIS项目实例
		QgsProject* project = QgsProject::instance();
		// 根据图层名称获取图层对象列表
		QList<QgsMapLayer*> layers = project->mapLayersByName(currentLayerName);

		QgsMapLayer* layer = nullptr;
		if (!layers.isEmpty()) {
			layer = layers.first();
		}

		// 禁用图层选择下拉框
		mpEditAction->setEnabled(false);
		mpEditLayerComboBox->setEnabled(false);

		if (layer && layer->type() == Qgis::LayerType::Vector) {
			// 检查图层的几何类型
			QgsVectorLayer* vectorLayer = static_cast<QgsVectorLayer*>(layer);
			switch (vectorLayer->geometryType()) {
			case Qgis::GeometryType::Point:
				mpCreatePointAction->setEnabled(true);
				mpCreateLineAction->setEnabled(false);
				mpCreatePolygonAction->setEnabled(false);
				break;
			case Qgis::GeometryType::Line:
				mpCreatePointAction->setEnabled(false);
				mpCreateLineAction->setEnabled(true);
				mpCreatePolygonAction->setEnabled(false);
				break;
			case Qgis::GeometryType::Polygon:
				mpCreatePointAction->setEnabled(false);
				mpCreateLineAction->setEnabled(false);
				mpCreatePolygonAction->setEnabled(true);
				break;
			default:
				// 如果图层类型不支持编辑，禁用所有创建按钮
				mpCreatePointAction->setEnabled(false);
				mpCreateLineAction->setEnabled(false);
				mpCreatePolygonAction->setEnabled(false);
				break;
			}
		}
		else {
			// 如果没有选中图层或图层不是矢量图层，禁用所有创建按钮
			mpCreatePointAction->setEnabled(false);
			mpCreateLineAction->setEnabled(false);
			mpCreatePolygonAction->setEnabled(false);
		}
	}
	else {
		// 退出编辑模式，取消所有编辑
		mpCreatePointAction->setEnabled(false);
		mpCreateLineAction->setEnabled(false);
		mpCreatePolygonAction->setEnabled(false);
	}
}

// 创建点要素的槽函数
void MainWindow::onCreatePointClicked() {
	QString currentLayerName = mpEditLayerComboBox->currentText();
	QgsProject* project = QgsProject::instance();
	// 根据图层名称获取图层对象列表
	QList<QgsMapLayer*> layers = project->mapLayersByName(currentLayerName);
	QgsMapLayer* layer = nullptr;

	if (!layers.isEmpty()) {
		layer = layers.first();
	}

	if (!layers.isEmpty() && layers.first()->type() == Qgis::LayerType::Vector) {
		QgsVectorLayer* vectorLayer = static_cast<QgsVectorLayer*>(layers.first());
		if (vectorLayer->geometryType() == Qgis::GeometryType::Point) {
			// 创建并设置 EditView
			EditView* editView = new EditView(mpMapCanvas);
			editView->setLayer(vectorLayer, EditView::PointMode);
			mpMapCanvas->setMapTool(editView);
		}
		else {
			QMessageBox::warning(this, tr("错误"), tr("选中的图层不是点图层！"));
		}
	}
	else {
		QMessageBox::warning(this, tr("错误"), tr("未选中有效的图层！"));
	}
}


void MainWindow::onCreateLineClicked()
{
	QString currentLayerName = mpEditLayerComboBox->currentText();
	QgsProject* project = QgsProject::instance();
	QList<QgsMapLayer*> layers = project->mapLayersByName(currentLayerName);

	if (!layers.isEmpty() && layers.first()->type() == Qgis::LayerType::Vector) {
		QgsVectorLayer* vectorLayer = static_cast<QgsVectorLayer*>(layers.first());

		// 检查图层是否为线图层
		if (vectorLayer->geometryType() == Qgis::GeometryType::Line) {
			// 创建并设置 EditView
			EditView* editView = new EditView(mpMapCanvas);
			editView->setLayer(vectorLayer, EditView::LineMode);  // 启用线段编辑模式
			mpMapCanvas->setMapTool(editView);
		}
		else {
			QMessageBox::warning(this, tr("错误"), tr("选中的图层不是线图层！"));
		}
	}
	else {
		QMessageBox::warning(this, tr("错误"), tr("未选中有效的图层！"));
	}
}


void MainWindow::onCreatePolygonClicked()
{
	QString currentLayerName = mpEditLayerComboBox->currentText();
	QgsProject* project = QgsProject::instance();
	QList<QgsMapLayer*> layers = project->mapLayersByName(currentLayerName);

	if (!layers.isEmpty() && layers.first()->type() == Qgis::LayerType::Vector) {
		QgsVectorLayer* vectorLayer = static_cast<QgsVectorLayer*>(layers.first());

		// 检查图层是否为多边形图层
		if (vectorLayer->geometryType() == Qgis::GeometryType::Polygon) {
			// 创建并设置 EditView
			EditView* editView = new EditView(mpMapCanvas);
			editView->setLayer(vectorLayer, EditView::PolygonMode);  // 启用多边形编辑模式
			mpMapCanvas->setMapTool(editView);
		}
		else {
			QMessageBox::warning(this, tr("错误"), tr("选中的图层不是多边形图层！"));
		}
	}
	else {
		QMessageBox::warning(this, tr("错误"), tr("未选中有效的图层！"));
	}
}

void MainWindow::onEditSaveClicked()
{
	QString currentLayerName = mpEditLayerComboBox->currentText();
	QgsProject* project = QgsProject::instance();
	QList<QgsMapLayer*> layers = project->mapLayersByName(currentLayerName);

	if (!layers.isEmpty() && layers.first()->type() == Qgis::LayerType::Vector) {
		QgsVectorLayer* vectorLayer = static_cast<QgsVectorLayer*>(layers.first());

		// 检查图层是否处于编辑模式
		if (vectorLayer->isEditable()) {
			// 提交图层的更改
			if (vectorLayer->commitChanges()) {
				QMessageBox::information(this, tr("保存成功"), tr("编辑已成功保存。"));
			}
			else {
				QMessageBox::warning(this, tr("保存失败"), tr("无法保存更改，请检查错误！"));
				vectorLayer->rollBack();  // 如果提交失败，回滚到之前的状态
			}
		}
		else {
			QMessageBox::warning(this, tr("错误"), tr("图层不在编辑模式，无法保存！"));
		}
	}

	// 重置地图工具，退出编辑状态
	resetMapTool();
}

void MainWindow::onEditCancelClicked()
{
	QString currentLayerName = mpEditLayerComboBox->currentText();
	QgsProject* project = QgsProject::instance();
	QList<QgsMapLayer*> layers = project->mapLayersByName(currentLayerName);

	if (!layers.isEmpty() && layers.first()->type() == Qgis::LayerType::Vector) {
		QgsVectorLayer* vectorLayer = static_cast<QgsVectorLayer*>(layers.first());

		// 检查图层是否处于编辑模式
		if (vectorLayer->isEditable()) {
			vectorLayer->rollBack();
			QMessageBox::information(this, tr("取消编辑"), tr("所有未保存的更改已被取消。"));
		}
		else {
			QMessageBox::warning(this, tr("错误"), tr("图层不在编辑模式，无法取消编辑！"));
		}
	}

	// 重置地图工具，退出编辑状态
	resetMapTool();
}

void MainWindow::resetMapTool()
{
	// 将地图工具重置为平移工具
	QgsMapToolPan* panTool = new QgsMapToolPan(mpMapCanvas);
	mpMapCanvas->setMapTool(panTool);

	// 恢复按钮状态
	mpEditAction->setEnabled(true);
	mpEditLayerComboBox->setEnabled(true);
	mpEditAction->setChecked(false);
	setEditState(false);
}

// 创建边栏窗口
void MainWindow::createDockWidgets()
{
	// 创建浏览器上侧左边栏
	QDockWidget* mpLeftTopDock = new QDockWidget(tr("浏览器"), this);
	mpLeftTopDock->setAllowedAreas(Qt::LeftDockWidgetArea);

	// 创建文件树
	mpFileTreeWidget->setHeaderLabel(tr("文件"));
	mpFileTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
	connect(mpFileTreeWidget, &QTreeWidget::customContextMenuRequested, mLayerManager, &LayerManager::onFileTreeContextMenu);
	mpLeftTopDock->setWidget(mpFileTreeWidget);
	addDockWidget(Qt::LeftDockWidgetArea, mpLeftTopDock);

	// 创建选择目录按钮
	QToolButton* selectDirectoryButton = new QToolButton(mpLeftTopDock);
	selectDirectoryButton->setText(tr("选择目录"));
	connect(selectDirectoryButton, &QToolButton::clicked, mLayerManager, &LayerManager::selectDirectory);

	// 将按钮和文件树控件添加到垂直布局中
	QVBoxLayout* layout = new QVBoxLayout();
	layout->addWidget(selectDirectoryButton);
	layout->addWidget(mpFileTreeWidget);
	QWidget* container = new QWidget();
	container->setLayout(layout);
	mpLeftTopDock->setWidget(container);

	// 用当前目录填充文件树
	mLayerManager->populateFileTree(QDir::currentPath());

	// 创建图层下侧左边栏
	QDockWidget* mpLeftBottomDock = new QDockWidget(tr("图层"), this);
	mpLeftBottomDock->setAllowedAreas(Qt::LeftDockWidgetArea);
	addDockWidget(Qt::LeftDockWidgetArea, mpLeftBottomDock);

	// 创建图层树模型并设置属性
	QgsLayerTreeModel* mpLayerTreeModel = new QgsLayerTreeModel(QgsProject::instance()->layerTreeRoot(), this);
	mpLayerTreeModel->setFlag(QgsLayerTreeModel::AllowNodeChangeVisibility);
	mpLayerTreeView->setModel(mpLayerTreeModel);
	mpLayerTreeView->setDropIndicatorShown(true);

	// 连接图层树模型的数据更改信号与更新地图画布图层的槽函数
	connect(mpLayerTreeModel, &QAbstractItemModel::dataChanged, mLayerManager, &LayerManager::updateMapCanvasLayers);

	mpLeftBottomDock->setWidget(mpLayerTreeView);

	// 设置图层树视图的上下文菜单
	mpLayerTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
	connect(mpLayerTreeView, &QgsLayerTreeView::customContextMenuRequested, mLayerManager, &LayerManager::showLayerTreeContextMenu);

	// 创建右侧顶部的工具箱边栏
	QDockWidget* mpRightDock = new QDockWidget(tr("工具箱"), this);
	mpRightDock->setAllowedAreas(Qt::RightDockWidgetArea);
	addDockWidget(Qt::RightDockWidgetArea, mpRightDock);
	QVBoxLayout* mpToolLayout = new QVBoxLayout();
	QWidget* toolWidget = new QWidget(this);
	QTreeWidget* mpToolTree = new QTreeWidget(toolWidget);
	mpToolTree->setHeaderHidden(true); // 隐藏表头

	// 工具栏工具树
	QTreeWidgetItem* mpVectorAnalysisItem = new QTreeWidgetItem(mpToolTree);
	mpVectorAnalysisItem->setText(0, tr("矢量分析"));
	QTreeWidgetItem* mpKMeansItem = new QTreeWidgetItem(mpVectorAnalysisItem);
	mpKMeansItem->setText(0, tr("K均值聚类"));
	QTreeWidgetItem* mpSpatialJoinItem = new QTreeWidgetItem(mpVectorAnalysisItem);
	mpSpatialJoinItem->setText(0, tr("按位置连接属性"));

	QTreeWidgetItem* mpRasterAnalysisItem = new QTreeWidgetItem(mpToolTree);
	mpRasterAnalysisItem->setText(0, tr("栅格分析"));
	QTreeWidgetItem* mpRasterStatsItem = new QTreeWidgetItem(mpRasterAnalysisItem);
	mpRasterStatsItem->setText(0, tr("栅格图层统计"));

	QTreeWidgetItem* mpSymItem = new QTreeWidgetItem(mpToolTree);
	mpSymItem->setText(0, tr("符号系统"));
	QTreeWidgetItem* mpClassItem = new QTreeWidgetItem(mpSymItem);
	mpClassItem->setText(0, tr("按类别符号化图层-唯一值"));

	mpToolLayout->addWidget(mpToolTree);
	toolWidget->setLayout(mpToolLayout);
	mpRightDock->setWidget(toolWidget);

	// 将工具树各选项与实现函数链接
	connect(mpToolTree, &QTreeWidget::itemClicked, this, [=](QTreeWidgetItem* item, int) {
		if (item == mpKMeansItem) {
			mVectorAnalysis->performKMeansClustering();
		}
		else if (item == mpSpatialJoinItem) {
			mVectorAnalysis->performSpatialJoin();
		}
		else if (item == mpRasterStatsItem) {
			mRasterAnalysis->performRasterLayerStatistics();
		}
		else if (item == mpClassItem) {
			mLayerManager->performCategorizedSymbology();
		}
		});
}

// 创建地图画布
void MainWindow::createMapCanvas()
{
	mpMapCanvas->setCanvasColor(Qt::white);
	mpMapCanvas->freeze(false);

	// 创建平移工具并设置为地图画布的当前工具
	QgsMapToolPan* mpPanTool = new QgsMapToolPan(mpMapCanvas);
	mpMapCanvas->setMapTool(mpPanTool);
	setCentralWidget(mpMapCanvas); // 设置为主窗口的中央控件
}

// 创建状态栏
void MainWindow::createStatusBar()
{
	QStatusBar* mpStatusBar = new QStatusBar(this);
	setStatusBar(mpStatusBar);

	// 坐标标签
	mpCoordinatesLabel = new QLabel("坐标: ", this);
	mpStatusBar->addPermanentWidget(mpCoordinatesLabel);

	// 坐标系标签
	mpCrsLabel = new QLabel("图层坐标系: ", this);
	mpStatusBar->addPermanentWidget(mpCrsLabel);

	// 连接图层可见性变化信号
	connect(mpLayerTreeView->model(), &QgsLayerTreeModel::dataChanged, this, &MainWindow::updateCrsInfo);

	// 比例尺标签，可选择常用比例
	mpScaleComboBox = new QComboBox(this);
	QStringList mScales = { "1:1000", "1:2500", "1:5000", "1:10000", "1:25000", "1:50000", "1:100000", "1:250000", "1:500000", "1:1000000" };
	mpScaleComboBox->addItems(mScales);
	mpScaleComboBox->setEditable(true);
	mpStatusBar->addPermanentWidget(new QLabel("比例: ", this));
	mpStatusBar->addPermanentWidget(mpScaleComboBox);

	// 旋转角度标签
	mpRotationSpinBox = new QDoubleSpinBox(this);
	mpRotationSpinBox->setRange(-360, 360);
	mpRotationSpinBox->setSingleStep(5);
	mpRotationSpinBox->setSuffix("°");
	mpStatusBar->addPermanentWidget(new QLabel("旋转角度: ", this));
	mpStatusBar->addPermanentWidget(mpRotationSpinBox);

	// 连接比例尺下拉框和旋转角度调整框的信号
	connect(mpScaleComboBox, &QComboBox::currentTextChanged, this, &MainWindow::updateScale);
	connect(mpRotationSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &MainWindow::updateRotation);

	// 连接更新坐标、比例、旋转角度标签的信号
	connect(mpMapCanvas, &QgsMapCanvas::xyCoordinates, this, &MainWindow::updateCoordinates);

	connect(mpMapCanvas, &QgsMapCanvas::scaleChanged, this, [this](double scale) {
		mpScaleComboBox->setCurrentText(QString("1:%1").arg(static_cast<int>(scale)));
		});

	connect(mpMapCanvas, &QgsMapCanvas::rotationChanged, this, [this](double rotation) {
		mpRotationSpinBox->setValue(rotation);
		});

	// 状态栏背景设置为灰色
	mpStatusBar->setStyleSheet("QStatusBar { background-color: lightgray; }");

	// 连接鼠标移动事件
	mpMapCanvas->setMouseTracking(true);
	connect(mpMapCanvas, &QgsMapCanvas::xyCoordinates, this, &MainWindow::updateCoordinates);

	// 创建新行用于进度条和状态标签
	QWidget* progressBarContainer = new QWidget(this);
	QHBoxLayout* progressBarLayout = new QHBoxLayout(progressBarContainer);
	progressBarLayout->setContentsMargins(0, 0, 0, 0);

}

void MainWindow::updateCoordinates(const QgsPointXY& point)
{
	// 判断坐标是否为地理坐标系
	bool isGeographic = qAbs(point.x()) <= 180 && qAbs(point.y()) <= 90;

	if (isGeographic)
	{
		QString xDirection = point.x() >= 0 ? "E" : "W";
		QString yDirection = point.y() >= 0 ? "N" : "S";
		mpCoordinatesLabel->setText(QString("坐标: %1°%2, %3°%4")
			.arg(qAbs(point.x())).arg(xDirection)
			.arg(qAbs(point.y())).arg(yDirection));
	}
	else
	{
		// 如果是投影坐标系，显示投影坐标系的 xy 坐标并加上单位
		mpCoordinatesLabel->setText(QString("坐标: X: %1 m, Y: %2 m").arg(point.x(), 0, 'f', 2).arg(point.y(), 0, 'f', 2));
	}
}

// 更新比例尺
void MainWindow::updateScale()
{
	double scale = mpScaleComboBox->currentText().remove("1:").toDouble();
	if (scale > 0)
	{
		mpMapCanvas->zoomScale(scale);
	}
}

// 更新旋转角度
void MainWindow::updateRotation()
{
	double rotation = mpRotationSpinBox->value();
	mpMapCanvas->setRotation(rotation);
}

// 打开工程文件
void MainWindow::openProject()
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("打开工程文件"), "", tr("工程文件 (*.qgz *.qgs)"));
	if (!fileName.isEmpty()) {
		QgsProject* project = QgsProject::instance();
		project->clear(); // 清理当前工程

		if (project->read(fileName)) {
			// 加载成功
			QMessageBox::information(this, tr("打开工程文件"), tr("工程文件已成功打开。"));
		}
		else {
			// 加载失败
			QMessageBox::warning(this, tr("打开工程文件"), tr("工程文件打开失败。"));
		}
	}
}


// 保存工程文件
void MainWindow::saveProject() {
	// 获取保存文件路径
	QString fileName = QFileDialog::getSaveFileName(this,
		tr("保存工程文件"),
		"",
		tr("QGIS 项目文件 (*.qgz *.qgs)"));

	// 如果用户取消了保存操作，文件名将是空的
	if (fileName.isEmpty()) {
		return;
	}

	// 根据用户选择的文件名后缀，确保文件名以.qgz或.qgs结尾
	if (!fileName.endsWith(".qgz") && !fileName.endsWith(".qgs")) {
		// 如果用户未手动添加后缀，可以根据文件过滤器默认选择.qgs
		fileName += ".qgs";
	}

	// 保存项目
	QgsProject* project = QgsProject::instance();
	if (project->write(fileName)) {
		// 保存成功
		QMessageBox::information(this, tr("保存工程文件"), tr("工程文件已成功保存。"));
	}
	else {
		// 保存失败
		QMessageBox::warning(this, tr("保存工程文件"), tr("工程文件保存失败。"));
	}
}


// 关于信息窗口
void MainWindow::about() {
	if (!mpAboutMessageBox) {
		mpAboutMessageBox = new QMessageBox(this);
		mpAboutMessageBox->setIcon(QMessageBox::Information);
		mpAboutMessageBox->setWindowTitle(tr("关于"));
		mpAboutMessageBox->setText(tr("作者: 谢宇瀚\n中国地质大学(武汉) 地理与信息工程学院 114222\nmail:872447672@qq.com\n2024.10"));
		mpAboutMessageBox->setStandardButtons(QMessageBox::Ok);
	}
	mpAboutMessageBox->exec();
}

// 打开通过QGIS的API制作的样式管理器
void MainWindow::openStyleManager()
{
	// 获取 QGIS 项目默认的样式实例
	QgsStyle* defaultStyle = QgsStyle::defaultStyle();
	if (!defaultStyle) {
		QMessageBox::warning(this, tr("错误"), tr("无法加载默认样式。"));
		return;
	}

	// 创建样式管理器对话框
	QgsStyleManagerDialog* styleManagerDialog = new QgsStyleManagerDialog(defaultStyle, this);
	styleManagerDialog->setAttribute(Qt::WA_DeleteOnClose);
	styleManagerDialog->show();  // 显示样式管理器
}

// 打开自己制作的样式管理器
void MainWindow::openSymbolManager()
{
	if (!mSymbolManager) {
		mSymbolManager = new SymbolManager(this);
	}
	mSymbolManager->show(); // 显示样式管理器
}

void MainWindow::updateCrsInfo()
{
	// 获取当前选中的图层
	const auto layers = QgsProject::instance()->layerTreeRoot()->checkedLayers();

	// 当且仅当有一个图层被勾选时，显示其坐标系信息
	if (layers.size() == 1) {
		QgsMapLayer* layer = layers.first();
		if (layer) {
			// 获取图层的坐标系
			const QgsCoordinateReferenceSystem crs = layer->crs();

			// 检查是否为地理坐标系
			QString geographicCrs, projectedCrs;
			if (crs.isGeographic()) {
				geographicCrs = crs.description(); // 地理坐标系描述
				projectedCrs = "无"; // 无投影坐标系
			}
			else {
				// 若为投影坐标系
				QgsCoordinateReferenceSystem geoCrs = crs.toGeographicCrs(); // 获取地理基准坐标系
				geographicCrs = geoCrs.description();
				projectedCrs = crs.description(); // 投影坐标系描述
			}

			// 组合显示地理和投影坐标系
			QString crsDescription = QString("地理坐标系: %1 - 投影坐标系: %2")
				.arg(geographicCrs)
				.arg(projectedCrs);

			// 更新状态栏标签
			mpCrsLabel->setText(crsDescription);
		}
	}
	else {
		// 如果没有图层或多个图层被勾选，清空坐标系信息
		mpCrsLabel->setText("坐标系: 未选择或多个图层");
	}
}

// 投影实现函数
void MainWindow::performProjectionTransformation()
{
	ProjectionTransformDialog* dialog = new ProjectionTransformDialog(mpMapCanvas, this);
	dialog->setModal(false);  // 设置为非模态
	dialog->show();
	GDALAllRegister();
	OGRRegisterAll();

	if (dialog->exec() == QDialog::Accepted) {
		QgsCoordinateReferenceSystem targetCrs = dialog->targetCrs();
		QString outputPath = QFileDialog::getSaveFileName(this, tr("保存转换后的文件"), "", tr("*.shp;;*.geojson;;*.tif;;*.qgs"));
		if (outputPath.isEmpty()) {
			return;
		}

		QString driverName;
		if (outputPath.endsWith(".shp", Qt::CaseInsensitive)) {
			driverName = "ESRI Shapefile";
		}
		else if (outputPath.endsWith(".geojson", Qt::CaseInsensitive)) {
			driverName = "GeoJSON";
		}
		else if (outputPath.endsWith(".tif", Qt::CaseInsensitive)) {
			driverName = "GTiff";
		}
		else if (outputPath.endsWith(".qgs", Qt::CaseInsensitive)) {
			driverName = "qgs";
		}
		else {
			QMessageBox::warning(this, tr("错误"), tr("不支持的文件格式！"));
			return;
		}

		QList<QgsMapLayer*> originalLayers;

		// 判断图层来源：如果选择文件则使用选定文件的路径
		if (dialog->mLayerSourceComboBox->currentIndex() == 0) {
			originalLayers.append(dialog->selectedLayer());
		}
		else {
			QString inputPath = dialog->selectedFile();
			if (inputPath.isEmpty()) {
				QMessageBox::warning(this, tr("错误"), tr("请选择文件。"));
				return;
			}

			// 检查是否为QGS项目文件
			if (inputPath.endsWith(".qgs", Qt::CaseInsensitive)) {
				QgsProject* tempProject = new QgsProject();
				if (!tempProject->read(inputPath)) {
					QMessageBox::warning(this, tr("错误"), tr("无法加载QGS项目文件。"));
					return;
				}
				originalLayers = tempProject->mapLayers().values();

				if (originalLayers.isEmpty()) {
					QMessageBox::warning(this, tr("错误"), tr("QGS项目文件中没有图层。"));
					return;
				}
			}
			else {
				// 支持加载非QGS项目文件的矢量和栅格图层
				QgsMapLayer* vectorLayer = new QgsVectorLayer(inputPath, QFileInfo(inputPath).fileName(), "ogr");
				if (vectorLayer && vectorLayer->isValid()) {
					originalLayers.append(vectorLayer);
				}
				else {
					QgsRasterLayer* rasterLayer = new QgsRasterLayer(inputPath, QFileInfo(inputPath).fileName());
					if (rasterLayer && rasterLayer->isValid()) {
						originalLayers.append(rasterLayer);
					}
					else {
						QMessageBox::warning(this, tr("错误"), tr("选定图层无效。"));
						return;
					}
				}
			}
		}

		// 遍历每个原始图层进行投影转换
		for (QgsMapLayer* originalLayer : originalLayers) {
			QString inputPath = originalLayer->dataProvider()->dataSourceUri(); // 获取当前图层的数据源路径

			if (originalLayer->type() == Qgis::LayerType::Vector) {
				// 处理矢量图层
				if (driverName == "qgs") {
					// 创建新的QgsProject实例
					QgsProject newProject;

					// 遍历每个原始图层，进行处理
					for (QgsMapLayer* originalLayer : originalLayers) {
						// 创建新的图层
						QgsMapLayer* newLayer = originalLayer->clone(); // 克隆原始图层
						if (newLayer) {
							// 转换坐标参考系统
							newLayer->setCrs(targetCrs); // 设置目标CRS

							// 添加到新的项目中
							newProject.addMapLayer(newLayer);
						}
					}

					// 保存新的QGS项目文件
					if (!newProject.write(outputPath)) {
						QMessageBox::warning(this, tr("错误"), tr("无法保存QGS项目文件。"));
						return;
					}

					QMessageBox::information(this, tr("投影转换成功"), tr("QGS项目已成功转换并保存。"));
				}
				else {
					// 处理矢量图层
					GDALDataset* poSrcDS = (GDALDataset*)GDALOpenEx(inputPath.toUtf8().constData(), GDAL_OF_VECTOR, nullptr, nullptr, nullptr);
					if (poSrcDS == nullptr) {
						QMessageBox::warning(this, tr("错误"), tr("无法打开源数据集。"));
						return;
					}

					OGRLayer* poLayer = poSrcDS->GetLayer(0);
					if (poLayer == nullptr) {
						GDALClose(poSrcDS);
						QMessageBox::warning(this, tr("错误"), tr("无法获取源图层。"));
						return;
					}

					OGRSpatialReference oTargetSRS;
					oTargetSRS.importFromWkt(targetCrs.toWkt().toUtf8().constData());

					GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName(driverName.toUtf8().constData());
					if (poDriver == nullptr) {
						GDALClose(poSrcDS);
						QMessageBox::warning(this, tr("错误"), tr("指定的驱动未找到。"));
						return;
					}

					// 设置编码为 UTF-8，防止中文乱码
					char** papszOptions = nullptr;
					papszOptions = CSLSetNameValue(papszOptions, "ENCODING", "UTF-8");

					GDALDataset* poDstDS = poDriver->Create(outputPath.toUtf8().constData(), 0, 0, 0, GDT_Unknown, papszOptions);
					if (poDstDS == nullptr) {
						GDALClose(poSrcDS);
						QMessageBox::warning(this, tr("错误"), tr("无法创建目标数据集。"));
						return;
					}

					OGRLayer* poDstLayer = poDstDS->CreateLayer(poLayer->GetName(), &oTargetSRS, poLayer->GetGeomType(), nullptr);
					if (poDstLayer == nullptr) {
						GDALClose(poSrcDS);
						GDALClose(poDstDS);
						QMessageBox::warning(this, tr("错误"), tr("无法创建目标图层。"));
						return;
					}

					// 设置图层编码
					poDstLayer->SetMetadataItem("ENCODING", "UTF-8");

					// 创建字段并确保支持UTF-8字符
					OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
					for (int i = 0; i < poFDefn->GetFieldCount(); i++) {
						OGRFieldDefn* poFieldDefn = poFDefn->GetFieldDefn(i);
						poDstLayer->CreateField(poFieldDefn);
					}

					OGRFeature* poFeature;
					poLayer->ResetReading();
					while ((poFeature = poLayer->GetNextFeature()) != nullptr) {
						OGRFeature* poDstFeature = OGRFeature::CreateFeature(poDstLayer->GetLayerDefn());
						poDstFeature->SetFrom(poFeature);
						OGRGeometry* poGeometry = poFeature->GetGeometryRef();
						if (poGeometry != nullptr) {
							poGeometry->transformTo(&oTargetSRS);
							poDstFeature->SetGeometry(poGeometry);
						}
						if (poDstLayer->CreateFeature(poDstFeature) != OGRERR_NONE) {
							qDebug() << "创建要素失败。";
						}
						OGRFeature::DestroyFeature(poFeature);
						OGRFeature::DestroyFeature(poDstFeature);
					}

					GDALClose(poSrcDS);
					GDALClose(poDstDS);

					QgsVectorLayer* transformedLayer = new QgsVectorLayer(outputPath, QFileInfo(outputPath).baseName(), "ogr");
					if (transformedLayer->isValid()) {
						QgsProject::instance()->addMapLayer(transformedLayer);
						QMessageBox::information(this, tr("投影转换成功"), tr("文件已成功转换并加载。"));
					}
					else {
						QMessageBox::warning(this, tr("投影转换失败"), tr("转换后的文件无效，请检查格式和路径。"));
					}
				}
			}
			else if (originalLayer->type() == Qgis::LayerType::Raster) {
				// 处理栅格图层
				GDALDataset* poSrcDS = (GDALDataset*)GDALOpen(inputPath.toUtf8().constData(), GA_ReadOnly);
				if (poSrcDS == nullptr) {
					QMessageBox::warning(this, tr("错误"), tr("无法打开源数据集。"));
					return;
				}

				OGRSpatialReference oTargetSRS;
				oTargetSRS.importFromWkt(targetCrs.toWkt().toUtf8().constData());

				GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName(driverName.toUtf8().constData());
				if (poDriver == nullptr) {
					GDALClose(poSrcDS);
					QMessageBox::warning(this, tr("错误"), tr("指定的驱动未找到。"));
					return;
				}

				GDALDataset* poDstDS = poDriver->CreateCopy(outputPath.toUtf8().constData(), poSrcDS, FALSE, nullptr, nullptr, nullptr);
				if (poDstDS == nullptr) {
					GDALClose(poSrcDS);
					QMessageBox::warning(this, tr("错误"), tr("无法创建目标数据集。"));
					return;
				}

				// 设置目标坐标系
				char* pszTargetWKT = nullptr;
				oTargetSRS.exportToWkt(&pszTargetWKT);
				poDstDS->SetProjection(pszTargetWKT);
				CPLFree(pszTargetWKT);

				CPLErr eErr = GDALReprojectImage(poSrcDS, nullptr, poDstDS, nullptr, GRA_Bilinear, 0.0, 0.0, nullptr, nullptr, nullptr);
				if (eErr != CE_None) {
					GDALClose(poSrcDS);
					GDALClose(poDstDS);
					QMessageBox::warning(this, tr("错误"), tr("栅格投影转换失败。"));
					return;
				}

				GDALClose(poSrcDS);
				GDALClose(poDstDS);

				QgsRasterLayer* transformedLayer = new QgsRasterLayer(outputPath, QFileInfo(outputPath).baseName(), "gdal");
				if (transformedLayer->isValid()) {
					transformedLayer->setCrs(targetCrs);
					QgsProject::instance()->addMapLayer(transformedLayer);
					mpMapCanvas->setDestinationCrs(transformedLayer->crs());
					mpMapCanvas->setExtent(transformedLayer->extent()); // 自动调整视图
					mpMapCanvas->refresh(); // 刷新地图画布
					QMessageBox::information(this, tr("投影转换成功"), tr("文件已成功转换并加载。"));
				}
				else {
					QMessageBox::warning(this, tr("投影转换失败"), tr("转换后的文件无效，请检查格式和路径。"));
				}
			}
		}
	}
}

QgsCoordinateReferenceSystem MainWindow::dataFrameCrs() const {
	return mDataFrameCrs;
}

void MainWindow::setDataFrameCrs(const QgsCoordinateReferenceSystem& crs) {
	mDataFrameCrs = crs;
	mDataFrameCrsSet = true;
	mpMapCanvas->setDestinationCrs(crs);  // 设置画布坐标系
	emit dataFrameCrsChanged(crs);  // 发出坐标系变更信号
}


void MainWindow::openDataFrameCrsDialog() {
	// 创建对话框
	QDialog dialog(this);
	dialog.resize(350, 150);
	dialog.setWindowTitle(tr("设置数据框坐标系"));

	QVBoxLayout* layout = new QVBoxLayout(&dialog);

	// 显示当前坐标系信息
	QLabel* currentCrsLabel = new QLabel(tr("当前数据框坐标系:"));
	layout->addWidget(currentCrsLabel);

	QString crsDescription = mDataFrameCrsSet ? mDataFrameCrs.description() : tr("未设置");
	QLabel* crsInfoLabel = new QLabel(crsDescription);
	layout->addWidget(crsInfoLabel);

	// 创建 QgsProjectionSelectionWidget
	QgsProjectionSelectionWidget* projectionSelector = new QgsProjectionSelectionWidget();
	layout->addWidget(projectionSelector);

	// 如果当前已设置数据框坐标系，则将其作为初始值显示在选择器中
	if (mDataFrameCrsSet) {
		projectionSelector->setCrs(mDataFrameCrs);
	}

	// "设置"按钮，点击时应用新的坐标系
	QPushButton* setButton = new QPushButton(tr("设置坐标系"));
	layout->addWidget(setButton);

	connect(setButton, &QPushButton::clicked, this, [=, &dialog]() {
		// 获取用户选择的坐标系
		QgsCoordinateReferenceSystem selectedCrs = projectionSelector->crs();
		if (selectedCrs.isValid()) {
			setDataFrameCrs(selectedCrs);  // 更新数据框坐标系
			crsInfoLabel->setText(selectedCrs.description());  // 更新显示
		}
		});

	// 添加对话框的按钮
	QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok, &dialog);
	layout->addWidget(buttonBox);
	connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);

	dialog.exec();
}

